import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * 异常
 *      异常的处理
 * 复习
 */
class Longin {
    public String userName = "admin";
    public String userWord = "123456";
    public void loginInfo(String userName,String userWord) {
        if(!this.userName.equals(userName)) {
            throw new UserNameException("登录账号错误...");
        }

        if(!this.userWord.equals(userWord)) {
            throw new UserWordException("登录密码错误...");
        }

        System.out.println("登录成功!");
    }
}
public class Test {
    /**
     * String类
     *      1.异常的处理
     * @param args
     *          1.异常的捕获
     *          2.异常的处理流程
     *      2.自定义异常
     */

    public static void main(String[] args) {
        /**
         * 自定义异常类
         *      自定义方式
         *          1.自定义异常类,类必须继承Exception(受查异常,必须需要程序员介入解决)/RuntimeException(非受查异常,可以由JVM进行解决)
         *          2.实现一个带String参数的构造方法,参数含义:出现异常原因
         * 注意事项
         *      1.继承类必须是Exception/RuntimeException
         *      2.继承Exception默认是受查异常
         *      2.继承RuntimeException默认是非受查异常
         */
        Longin longin = new Longin();

        try {
            longin.loginInfo("admin","123456");
        }catch(UserNameException userNameException) {
            userNameException.printStackTrace();
        }catch(UserWordException userWordException) {
            userWordException.printStackTrace();
        }
    }
    public static void main3(String[] args) {
        /**
         * 异常的处理流程
         *      调用栈:方法之间相互调用的关系
         *      栗子:虚拟机栈专门存储调用方法,
         *      方法中存在异常,方法没有进行处理,返回给调用方法的方法进行处理,该方法没处理则JVM进行处理就会和没有进行捕捉之前代码一样的情况
         * @param args
         * 流程总结:
         *      1.执行try代码块内代码,如果出现异常,则和catch异常进行匹配
         *      2.如果匹配的上就对该异常进行处理,处理完成后,跳出try-catch执行后续代码
         *      3.如果匹配不上就会传递给上层调用者
         *      4.无论是否匹配的上,finally代码块一定会被执行(方法结束前)
         *      5.如果上层调用者也没有对异常进行处理就继续向上传递
         *      6.一直传递到main方法依然没有进行处理的话,就交给JVM进行处理异常
         */
    }
    /**
     * 异常捕获
     * @param args
     *      声明throws
     *      try-catch
     *      finally
     */
    public static int func1() {
        Scanner scanner = new Scanner(System.in);
        try {
            int a = scanner.nextInt();
            return a;
        }catch(InputMismatchException e) {
            e.printStackTrace();
            System.out.println("捕捉到InterruptedException异常");
        }finally {
            System.out.println("finally执行了");
            scanner.close();//无论异常是否被捕捉,都会释放资源
            //return 99;//调用方法,返回99,所以finally是最后执行的,无论进行return
        }
        return -1;
    }
    public static void main2(String[] args) {
        /**
         * finally:有些特定的代码无论程序是否被执行,都必须执行,例如程序资源的关闭.所以一般finally使用于资源的关闭
         *
         * 注意事项
         *      1.不建议finally中存在return,因为必然最后执行,就不会返回原来return值
         *
         * 面试题
         * throw 与 throws的区别?
         *      一个是异常声明,一个是异常的抛出
         * finally语句一定会被执行吗?
         *      是的
         */
        func1();
    }
    public static void func(int[] array) {
        if(array == null) {
            throw new RuntimeException();
        }
    }
    public static void main1(String[] args) {
        /**
         * try-catch
         *      语法格式
         *      try {
         *          可能出现异常的代码
         *      }catch(异常类型 变量名){//如果发生的异常与类型异常相同时,就会进入该catch内代码进行处理
         *          //捕捉到之后就可以对异常进行处理,处理完成后,就可以跳出执行后面代码
         *      }[ catch(异常类型 变量名) {
         *
         *      }finally {
         *          此代码一定会执行到
         *      }]
         *
         * 异常的处理方法
         *      1.涉及到特别严重场景->钱,直接程序崩溃,防止严重后果
         *      2.涉及到不太严重场景,记录日志,通过提醒程序员进行修改
         *      3.涉及到游戏卡顿,进行重新加载,连接网络
         *
         * 注意事项:
         *      1.try中遇到异常后,try后面代码不再执行
         *      2.抛出多个异常,catch进行多次捕获,进行多次处理,如果具有父子关系,则子类型必须在前.
         *      3.可以捕捉全部个异常,一次处理(使用Exception作为捕捉类型,不建议)
         *      4.如果异常类型没有捕捉到,则会继续throws,直到JVM进行处理
         */
        try {
            func(null);
            System.out.println("try::");
        } catch(ArrayIndexOutOfBoundsException e) {//子类放在前面,父类放在后面进行捕捉
            e.printStackTrace();
            System.out.println("捕捉到数组越界异常");
        } catch(RuntimeException e) {
            e.printStackTrace();//打印异常
            System.out.println("出现异常");
        }
        System.out.println("after");
    }
}
